using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.Policy;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using Helper = PHSRAG.WebControls.Helper;
using InsightUtility = PHSRAG.Insight21.InsightUtilities;
using webControls = PHSRAG.WebControls;

namespace PHSRAG.Insight21.Humans.Details
{
    /// <summary>
    /// Shows the complete lifecycle of a protocol (initial review, and any continuing reviews,
    /// amendments, adverse events and/or other events associated with the protocol and the
    /// status of each submission)
    /// </summary>
    public partial class ProtocolDetails : BasePage
    {
        #region Constants (Keys)

        private const string AdverseEventReviewsKey = "adverseEventReviews_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string AdvEvSubCountKey = "adverseEventsSubCountKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string AEExpandedKey = "AEExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string AmendmentsReviewsKey = "amendments_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string AMExpandedKey = "AMExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string AMSubCountKey = "AMSubCountKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";

        /// <summary>
        /// the id of the protocol for which data is cached for (if cached)
        /// </summary>
        private const string CachedProtocolIdKey = "CachedProtocolIdKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string ContinuingReviewsKey = "continuingReviews_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string CRExpandedKey = "CRExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string CRSubCountKey = "CRSubCountKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string InitialReviewsKey = "initialReviews_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string IRExpandedKey = "IRExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string IRGridStatusKey = "IRGridStatusKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string NumberAdvEvPendingKey = "numberAdvEvPendingKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string NumberAMPendingKey = "NumberAMPendingKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string NumberCRPendingKey = "NumberCRPendingKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string NumberOEPendingKey = "NumberOEPendingKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string NumberTRPendingKey = "NumberTRPendingKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string OEExpandedKey = "VDExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string OESubCountKey = "otherEventsSubCountKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string OtherEventReviewsKey = "otherEventReviews_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";

        /// <summary>
        ///  stores data for the page
        /// </summary>
        private const string PageCacheKey = "protocolDetailsPage__9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string ProtocolKey = "Protocol_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string ToggleLockStatusTextWhenLocked = "Unlock Protocol";
        private const string ToggleLockStatusTextWhenUnlocked = "Lock Protocol";
        private const string TRExpandedKey = "CRExpanded_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string TriennialReviewsKey = "triennialReviews_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";
        private const string TRSubCountKey = "TRSubCountKey_9572FCDE-47B6-4e7b-921E-D32AE6F02D45";

        #endregion

        #region Non-Key Constants

        private const string AnnunciatorTitle = "The following error(s) occurred...";
        private const string CollapseImageURL = "../Images/CollapseButton.gif";
        private const string DeferredStatus = "Deferred";
        private const string ExpandImageURL = "../Images/ExpandButton.gif";
        private const string HoldStatus = "Hold";
        private const string NoRecordsDisplay = "0";
        private const string NoteImageURL = "../Images/Note.gif";
        private const string PendingStatus = "Pending";
        private const string PopUpFeatures = "width=600,height=400,scrollbars=yes,resizable=yes,status=no";
        private const string RemoveFlag = "RemoveFlag";
        private const string ReportImageURL = "../Images/Note.gif";
        private const string ReqModStatus = "Req. Mod.";
        private const string ToggleRowsCommand = "ToggleRows";
        private const string ViewApplicationCommand = "ViewApplication";
        private const string ViewImageURL = "../Images/PDF.gif";
        private const string ViewIRBNotesCommand = "ViewIRBNotes";
        private const string WorkFlowReportPage = "WorkFlowReport.aspx";

        #endregion

        #region Instance Variables (Private)      
        private int accessLevel;        
        protected ActivityIndicator activityIndicator;

        /// <summary>
        ///  once the first row of the Initial Review grid gets bound, this is true
        /// </summary>
        private bool boundFirstIR = false;
        private ICachePolicy cachePolicy;

        /// <summary>
        /// during itemdatabinding, these fields get set so that subsequent items getting bound can
        /// be determined to be grouped under the parent as child rows by comparing their formsId or 
        /// board name (if they are different, it indicates a new parent row being bound)
        /// </summary>
        private string currentFormsId;

        /// <summary>
        /// during binding a non-dominant row, this is used to determine whether the parent row is expanded
        /// (and if true, this child row is shown) --> this value gets overwritten by the parent row
        /// during ITs binding
        /// </summary>
        private bool expanded = false;
        private Hashtable pageCache;
        private ICachePolicy pageCachePolicy;
        private Protocol protocol;
        private int protocolId;
        private ProtocolProcess protocolProcess;
        private int protocolProcessId;

        /// <summary>
        /// boolean variable to determine whether or not to delete
        /// </summary>
        private bool removeDocument = false;

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets/Sets whether the Initial Review portion of the page is showing
        /// </summary>
        private bool IRExpanded
        {
            get
            {
                object o = pageCache[IRExpandedKey];
                return (o == null) ? (initialReview.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(IRExpandedKey, initialReviewContainer, initialReviewToggler, value); }
        }

        /// <summary>
        /// Gets/Sets whether the Continuing Reviews portion of the page is showing
        /// </summary>
        private bool CRExpanded
        {
            get
            {
                object o = pageCache[CRExpandedKey];
                return (o == null) ? (continuingReviews.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(CRExpandedKey, continuingReviewsContainer, crToggle, value); }
        }

        /// <summary>
        /// Gets/Sets whether the Triennial Reviews portion of the page is showing
        /// </summary>
        private bool TRExpanded
        {
            get
            {
                object o = pageCache[TRExpandedKey];
                return (o == null) ? (triennialReviews.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(TRExpandedKey, triennialReviewsContainer, trToggle, value); }
        }

        /// <summary>
        /// Gets/Sets whether the Amendments portion of the page is showing
        /// </summary>
        private bool AMExpanded
        {
            get
            {
                object o = pageCache[AMExpandedKey];
                return (o == null) ? (amendments.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(AMExpandedKey, amendmentsContainer, amToggler, value); }
        }

        /// <summary>
        /// Gets/Sets whether the Adverse Events portion of the page is showing
        /// </summary>
        private bool AEExpanded
        {
            get
            {
                object o = pageCache[AEExpandedKey];
                return (o == null) ? (adverseEvents.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(AEExpandedKey, adverseEventsContainer, aeToggler, value); }
        }

        /// <summary>
        /// Gets/Sets whether the Other Events portion of the page is showing
        /// </summary>
        private bool OEExpanded
        {
            get
            {
                object o = pageCache[OEExpandedKey];
                return (o == null) ? (otherEvents.Items.Count > 0) : (bool) o;
            }
            set { SetPanelExpandedState(OEExpandedKey, otherEventsContainer, oeToggler, value); }
        }

        /// <summary>
        /// Gets the protocol .If it's not already in the cache, it loads it up based on the protocolId passed to the page, and caches the object
        /// </summary>
        private Protocol Protocol
        {
            get
            {
                string cacheKey = Protocol.ProtocolKey;
                protocol = cachePolicy.GetCachedObject(cacheKey) as Protocol;

                if ((protocol == null) || (protocolId != protocol.Id))
                {
                    protocol = new Protocol(cachePolicy);
                    protocol.Load(DataAccess.GetConnectionString(), protocolId);
                    cachePolicy.Cache(cacheKey, protocol);
                }
                return protocol;
            }
        }

        /// <summary>
        /// Gets the protocol process . If it's not already
        /// in the cache, it loads it up based on the protocolProcessId passed to the page, and caches the 
        /// object
        /// </summary>
        private ProtocolProcess ProtocolProcess
        {
            get
            {
                protocolProcess = cachePolicy.GetCachedObject(ProtocolProcess.ProtocolProcessKey)
                    as ProtocolProcess;

                if ((protocolProcess == null) || (protocolProcessId != protocolProcess.Id))
                {
                    if (protocolProcessId != 0)
                    {
                        protocolProcess = ProtocolProcess.GetProtocolProcess(
                            DataAccess.GetConnectionString(), protocolProcessId, cachePolicy, null);
                        cachePolicy.Cache(ProtocolProcess.ProtocolProcessKey, protocolProcess);
                    }
                    else
                    {
                        protocolProcess = null;
                    }
                }

                return protocolProcess;
            }
        }

        /// <summary>
        /// Checks if the logged in user has the ability to edit(add/delete the notification letters)
        /// Only Workflow manager or the protocol adminitrator will be able to edit the grid
        /// </summary>
        private bool HasEditPermission
        {
            get
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                return ((Protocol.AdministratorId == userContext.DomainUserId) || (userContext.ModuleRoleBitmask & (int) ModuleRoleBit.WorkflowManager) > 0);
            }
        }

        #endregion

        /// <summary>
        /// Stores the setValue in the pageCache under the viewStateKey, sets the visibility on the panel to
        /// setValue, and sets the imageUrl of the toggler button based on setValue
        /// </summary>
        /// <param name="key">key to store the collapsed/expanded state of the panel in ViewState</param>
        /// <param name="panel">pabel to set visibility on</param>
        /// <param name="toggler">button to display image for</param>
        /// <param name="setValue">value to set panel visibility and button image from</param>
        private void SetPanelExpandedState(string key, Panel panel, ImageButton toggler, bool setValue)
        {
            pageCache[key] = setValue;
            pageCachePolicy.Cache(PageCacheKey, pageCache);
            panel.Visible = setValue;
            toggler.ImageUrl = setValue ? CollapseImageURL : ExpandImageURL;
        }

        #region Event Handlers

        /// <summary>
        /// Register a hidden field that will be used to identify whether or not the remove option is checked on the grid(for the editable row).
        /// </summary>
        /// <param name="e">arguments to render.</param>
        protected override void OnPreRender(EventArgs e)
        {
            try
            {
                base.OnPreRender(e);
                ClientScript.RegisterHiddenField(RemoveFlag, removeDocument.ToString());
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// All actions here are on non-postbacks only. The breadcrumb trail gets set and all grids 
        /// are set to a collapsed state.  The id for the protocol for which the page is displaying details
        /// is pulled from the cache.  The cache is also checked for a previous protocolId, and if they 
        /// are different, the cache is flushed of previous details.  The current protocol id is cached for
        /// future comparisions.  The datasources for the grids on the page get loaded here, but not bound to
        /// the grids.
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">arguments of the event</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                pageCache = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();

                breadCrumb.Add(
                    "Protocol Details",
                    Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""),
                    Settings.GetKeyValue("BreadCrumb.DetailPageLevel", 2));

                annunciator.Message = string.Empty;
                //Check if the remove option is checked on the grid(only one grid can be edited at a time)
                string removeData = Request.Form[RemoveFlag];
                removeDocument = (removeData != null && removeData == "True");

                if (!IsPostBack)
                {
                    // get id coming from the originating page and clean the cache of all incoming data
                    Hashtable incomingPageHash =
                        cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                    if (incomingPageHash != null)
                    {
                        protocolId = Convert.ToInt32(incomingPageHash[Keys.ProtocolIdKey]);
                        protocolProcessId = Convert.ToInt32(incomingPageHash[Keys.ProtocolProcessIdKey]);
                        accessLevel = Convert.ToInt32(incomingPageHash[Keys.ProtocolAccessKey]);
                        cachePolicy.UnCache(Keys.IncomingDataKey);

                        // get any data that's been cached from previous hits to the page;
                        // if there's data in the cache for this page, and if the protocolId is different 
                        // than the one for which data is cached, flush the cache
                        object cachedProtId = pageCache[CachedProtocolIdKey];
                        if (cachedProtId != null)
                        {
                            int cachedId = Convert.ToInt32(cachedProtId);
                            if (cachedId != protocolId)
                            {
                                UnCachePageData();
                                pageCache[CachedProtocolIdKey] = cachedId;
                            }
                        }
                        else
                        {
                            UnCachePageData();
                        }

                        pageCache[CachedProtocolIdKey] = protocolId;
                        pageCache[Keys.ProtocolProcessIdKey] = protocolProcessId;
                        pageCache[Keys.ProtocolAccessKey] = accessLevel;
                        pageCachePolicy.Cache(PageCacheKey, pageCache);
                    }
                }               
                
                protocolId = (int) pageCache[CachedProtocolIdKey];

                //For removing post back on Current View image button

                viewFullApplication.OnClientClick = "javascript:window.open('ViewProtocolPage.aspx?ViewApplicationType=FullUsingProtocolInformation&currentview=yes&ProtocolId=" + protocolId + "', 'ViewProtocolPage', 'width=800, height=600, status=yes, toolbar=no, resizable=yes');return false;";


                protocolDetailHeader.ProtocolID = protocolId;
                protocolProcessId = (int) pageCache[Keys.ProtocolProcessIdKey];
                accessLevel = (int) pageCache[Keys.ProtocolAccessKey];

                // Lock/Unlock is visible if the user has sufficient rights and
                // the Protocol's overall status is Pending or Submitted 
                // indicating the user came from the pending page, and the protocol
                // was created in insight
                string referringPage = "";
                ArrayList breadCrumbs = breadCrumb.BreadCrumbDetails;
                foreach (BreadCrumbInfo breadcrumbInfo in breadCrumbs)
                {
                    if (breadcrumbInfo.Level == 1)
                    {
                        referringPage = ((BreadCrumbInfo) (breadCrumbs[0])).NavigateUrl;
                        break;
                    }
                }

                int roleBitMask = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask;
                toggleProtocolLock.Visible =
                    ((roleBitMask & (int) ModuleRoleBit.LockUnlockProtocols) > 0)
                        && (Protocol.OverallStatus != Constants.ProtocolOverallStatusText.WorkInProgress)
                            && referringPage.IndexOf("PendingApplicationsPage") >= 0
                                && (ProtocolProcess != null);

                if (toggleProtocolLock.Visible)
                {
                    if (ProtocolProcess != null)
                    {
                        SetLockUnlockButton(ProtocolProcess.Locked);
                    }
                    else
                    {
                        SetLockUnlockButton(Protocol.IsLocked);
                    }
                }

                if (Protocol.IsLegacy)
                {
                    viewFullApplication.Visible = false;
                }

                LoadIRGrid();
                LoadCRGrid();
                LoadAmendmentsGrid();
                LoadAEGrid();
                if (Protocol.ModuleType == Constants.ModuleType.Animals)
                {
                    LoadTRGrid();
                    amendments.Columns.RemoveAt((int) AmendmentCellIndexes.SponsorAmendmentNumber);
                    continuingReviews.Columns[(int) ContinuingReviewCellIndexes.FormsId].HeaderText = "AR#";
                }
                else
                {
                    LoadOEGrid();
                }

                BindGrids();

                // set all grids to previous expanded or collapsed state
                IRExpanded = IRExpanded;
                CRExpanded = CRExpanded;
                TRExpanded = TRExpanded;
                AMExpanded = AMExpanded;
                AEExpanded = AEExpanded;
                OEExpanded = OEExpanded;

                if (Convert.ToBoolean(cachePolicy.GetCachedObject(Keys.ShowNewProcessBarKey)))
                {
                    if (((accessLevel & Protocol.ManagePermission) > 0 ||
                        (accessLevel & Protocol.EditPermission) > 0)
                            && Protocol.ProtocolTypeCode != Constants.NewAnimalsProtocolType.TissueApplication)
                    {
                        CreateNewProcessBar newProcessBar = (CreateNewProcessBar) Page.LoadControl("../Research/CreateNewProcessBar.ascx");
                        newProcessBar.ProtocolID = protocolId;
                        newProcessBar.UserAccessLevel = accessLevel;
                        newProcessBar.ModuleName = header.ModuleName;
                        newProcessPanel.Controls.Add(newProcessBar);
                    }
                }

                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

                if ((Protocol.AdministratorId == userContext.DomainUserId) || (userContext.ModuleRoleBitmask & (int) ModuleRoleBit.WorkflowManager) > 0)
                {
                    ArrayList consentForms = Protocol.GetProtocolDocuments(protocolId, FormsManagement.Constants.AttachmentType.ConsentForm, pageCachePolicy);
                    if (consentForms != null && consentForms.Count > 0)
                    {
                        ConsentFormPublisher consentFormPublisher = (ConsentFormPublisher) Page.LoadControl("../Research/ConsentFormPublisher.ascx");
                        consentFormPublisher.ProtocolID = protocolId;
                        consentFormPublisherPanel.Controls.Add(consentFormPublisher);
                    }
                }

                SetupPageForModuleType();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Make necessary changes to page for use by Animals or Humans
        /// </summary>
        protected void SetupPageForModuleType()
        {
            if (Protocol.ModuleType == Constants.ModuleType.Animals)
            {
                animalsSubModNavigation.Visible = true;
                humansSubModNavigation.Visible = false;
                animalsSubModNavigation.ProtocolProcess = ProtocolProcess;
                animalsSubModNavigation.Protocol = Protocol;
                animalsSubModNavigation.SelectedLink = "Protocol Details";
                crLabel.Text = "Annual";
                aeLabel.Text = "Deficiencies";
                otherEventsContainer.Visible = otherEventsHeader.Visible = false;
                triennialReviewsHeader.Visible = triennialReviewsContainer.Visible = true;
                cloneControls.Visible = true;
                bool bIRFound = false;
                foreach (ProtocolProcess process in Protocol.ProtocolProcesses)
                {
                    if (process.Type == Constants.AnimalProtocolProcessType.InitialReview)
                    {
                        bIRFound = true;
                    }
                }
                if (!bIRFound)
                {
                    cloneProtocol.ImageUrl = "~/Images/b_cloneprotocol_disabled.gif";
                    cloneProtocol.Enabled = false;
                    cloneDiv.Attributes["style"] = "width:150px;border:solid 2px #808080";
                    cloneOptions.Enabled = false;
                }
                protocolAbstract.Visible = (!string.IsNullOrEmpty(Protocol.ProtocolAbstract) && (Protocol.IsLegacy)) ? true : false;
            }
            else
            {
                //Set the Human sub mod Navigation links
                humansSubModNavigation.Visible = true;
                animalsSubModNavigation.Visible = false;
                humansSubModNavigation.ProtocolProcess = ProtocolProcess;
                humansSubModNavigation.Protocol = Protocol;
                humansSubModNavigation.SelectedLink = "Protocol Details";
            }
        }

        /// <summary>
        /// Clones the current protocol and navigates to the new protocol.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnCloneProtocol(object sender, ImageClickEventArgs e)
        {
            UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;

            bool includeStaff = cloneOptions.Items[0].Selected;
            bool includeAttachments = cloneOptions.Items[1].Selected;
            Protocol clone = Protocol.Clone(includeStaff, includeAttachments, userContext.DomainUserId);

            Hashtable outgoingData = new Hashtable();
            outgoingData.Add(Keys.ProtocolIdKey, clone.Id);
            outgoingData.Add(Keys.ProtocolProcessIdKey, pageCache[Keys.ProtocolProcessIdKey]);
            outgoingData.Add(Keys.ProtocolAccessKey, pageCache[Keys.ProtocolAccessKey]);
            pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
            outgoingData.Add("IsClone", true);
            Page.Response.Redirect(Settings.GetKeyValue("SubModuleNavigation.Humans.EditProtocolInfoPageURL", ""));
        }

        /// <summary>
        /// Displays the top row for each submission, and displays the child rows for the submissions
        /// depending on whether the parent/top row is expanded.  Also generates javascript to open IRB
        /// notes and assigns it to any note icons that appear in the rows
        /// </summary>
        /// <param name="sender">dataGrid</param>
        /// <param name="e">arguments to the event</param>
        private void OnIRItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                #region Identify & set edit Access

                TableCell editCell = e.Item.Cells[(int) ReviewCellIndexes.Edit];
                if (editCell != null)
                {
                    editCell.Visible = HasEditPermission;
                }

                TableCell remove = e.Item.Cells[(int) ReviewCellIndexes.Remove];
                if (remove != null)
                {
                    if (e.Item.ItemType == ListItemType.EditItem)
                    {
                        CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                        removeCheckBox.Enabled = true;
                        //Save the state of the checkbox in a hiddenfield, so that it can be obtained on the page load of a postback
                        removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                    }
                }
                TableCell fileUpload = e.Item.Cells[(int) ReviewCellIndexes.FileUpload];
                if (fileUpload != null)
                {
                    if (e.Item.ItemType == ListItemType.EditItem)
                    {
                        ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                    }
                }

                #endregion

                if (e.Item.ItemType == ListItemType.Item ||
                    e.Item.ItemType == ListItemType.AlternatingItem
                    )
                {
                    #region Item/Alternating item/edit item

                    // Check to see if it is the parent row (first IR hasn't been bound), or a child of the parent row.
                    if (!boundFirstIR)
                    {
                        boundFirstIR = true;
                        e.Item.CssClass = "DataGridItem";
                        e.Item.Visible = true;

                        if (((Review) e.Item.DataItem).Parent.ReviewCount > 1)
                        {
                            if (e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls.Count == 0)
                            {
                                StatefulToggleButton image = new StatefulToggleButton(
                                    ((DataGrid) sender).ID, e.Item.ItemIndex, pageCache);
                                e.Item.Cells[(int) ReviewCellIndexes.PlusSignIndex].Controls.Add(image);
                                // image is currently expanded, but after page is rendered it won't be expanded
                                // anymore
                                expanded = image.IsExpanded;
                            }
                        }

                        // handle creation of Workflow report icon, javscript and assignment of the javascript
                        // to the button Testing for Workflow Report					
                        if (((Label) e.Item.FindControl("protocolProcessIdIR")).Text != "0")
                        {
                            ImageButton reportImage = new ImageButton();
                            reportImage.ImageUrl = ReportImageURL;
                            reportImage.Attributes["onclick"] =
                                string.Format("window.open('{0}?PPId={1}', 'WorkflowReport', '{2}');return false;",
                                    WorkFlowReportPage, (((Label) e.Item.FindControl("protocolProcessIdIR")).Text), PopUpFeatures);

                            e.Item.Cells[(int) WorkFlowReportIndex.InitialReview].Controls.Add(reportImage);
                        }

                        if (((Review) e.Item.DataItem).ProtocolProcessId > 0)
                        {
                            //Prevent postback when user clicks on View PDF of IR grid
                            ImageButton viewImage = new ImageButton();
                            viewImage.ImageUrl = ViewImageURL;
                            viewImage.OnClientClick = "javascript:window.open('../Research/ViewProtocolPage.aspx?Report=view&ProtocolProcessId=" + ((Review) e.Item.DataItem).ProtocolProcessId + "', 'ViewProtocolPage', 'resizable=yes, status=yes, scrollbars=yes');return false;";
                            e.Item.Cells[(int) ViewApplicationIndex.InitialReview].Controls.Add(viewImage);
                            /* viewImage.CommandName = ViewApplicationCommand;
							 e.Item.Cells[(int)ViewApplicationIndex.InitialReview].Controls.Add(viewImage);
							 e.Item.Cells[(int)ReviewCellIndexes.ProtocolProcessId].Text =
								 ((Review)e.Item.DataItem).ProtocolProcessId.ToString();*/
                        }
                    }

                        // this is not a new parent row, so if the parent row of this grouping
                        // is expanded, show the child rows
                    else
                    {
                        e.Item.CssClass = "DataGridAlternatingItem";
                        e.Item.Visible = expanded;
                    }

                    // handle creation of IRB 3 icon, javscript and assignment of the javascript
                    // to the button

                    #endregion
                }

                if (e.Item.ItemType == ListItemType.Item ||
                    e.Item.ItemType == ListItemType.AlternatingItem ||
                        e.Item.ItemType == ListItemType.EditItem)
                {
                    if (((Label) e.Item.Cells[(int) ReviewCellIndexes.IRBNotes].Controls[1]).Text != string.Empty &&
                        Convert.ToInt32(((Label) e.Item.Cells[(int) ReviewCellIndexes.IRBNotes].Controls[1]).Text) > 0)
                    {
                        ImageButton noteImage = new ImageButton();
                        noteImage.ImageUrl = ViewImageURL;
                        // noteImage.CommandName = ViewIRBNotesCommand;
                        //Prevent Postback 
                        noteImage.OnClientClick = "javascript:window.open('../Research/DownloadForm.aspx?Report=viewreport&DocId=" + ((Label) e.Item.Cells[(int) ReviewCellIndexes.IRBNotes].Controls[1]).Text + "', 'ViewFile', 'resizable=yes, status=yes, scrollbars=yes');return false;";
                        e.Item.Cells[(int) NoteIndex.InitialReview].Controls.Add(noteImage);
                    }

                    for (int i = 0, cellCount = e.Item.Cells.Count; i < cellCount; ++i)
                    {
                        if (i != (int) Remove.InitialReview)
                        {
                            e.Item.Cells[i].EnableViewState = false;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This event will open the protocol abstract as RTF
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">arguments of the event</param>
        public void OnProtocolAbstract(object sender, ImageClickEventArgs e)
        {
            try
            {
                string mimeType = Helper.GetMimeType(".rtf");
                if (mimeType != null)
                {
                    Response.ContentType = mimeType;
                }

                Response.AppendHeader("content-disposition",
                    string.Format("attachment; filename={0}.rtf", Guid.NewGuid()));

                Response.Write(Protocol.ProtocolAbstract);

                // Call this to end the request instead of Response.End see MS KB 312629
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Creates the note icon for records that have IRB notes, and the javascript associated with it 
        /// to pop up the window; turns on/off visibility for each row within the grid based on whether
        /// the parent row is expanded/collapsed; If the item is the grid's header, it adds a "Toggle All"
        /// button if there are expandable rows in the grid
        /// </summary>
        /// <param name="sender">dataGrid</param>
        /// <param name="e">DataGridItem</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                string dataGridID = ((DataGrid) sender).ID;

                #region Identify & Set edit Access

                switch (dataGridID)
                {
                    case "continuingReviews":
                    {
                        TableCell editCell = e.Item.Cells[(int) Edit.ContinuingReviews];
                        if (editCell != null)
                        {
                            editCell.Visible = HasEditPermission;
                        }

                        TableCell remove = e.Item.Cells[(int) Remove.ContinuingReviews];
                        if (remove != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                                removeCheckBox.Enabled = true;
                                removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                            }
                        }

                        TableCell fileUpload = e.Item.Cells[(int) FileUploadIndex.ContinuingReviews];
                        if (fileUpload != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                            }
                        }
                        break;
                    }
                    case "amendments":
                    {
                        TableCell editCell = e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? ((int) Edit.Amendments) - 1 : (int) Edit.Amendments];
                        if (editCell != null)
                        {
                            editCell.Visible = HasEditPermission;
                        }

                        TableCell remove = e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) Remove.Amendments - 1 : (int) Remove.Amendments];
                        if (remove != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                                removeCheckBox.Enabled = true;
                                removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                            }
                        }
                        TableCell fileUpload = e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? ((int) FileUploadIndex.Amendments) - 1 : (int) FileUploadIndex.Amendments];
                        if (fileUpload != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                            }
                        }
                        break;
                    }
                    case "adverseEvents":
                    {
                        TableCell editCell = e.Item.Cells[(int) Edit.AdverseEvents];
                        if (editCell != null)
                        {
                            editCell.Visible = HasEditPermission;
                        }

                        TableCell remove = e.Item.Cells[(int) Remove.AdverseEvents];
                        if (remove != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                                removeCheckBox.Enabled = true;
                                removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                            }
                        }

                        TableCell fileUpload = e.Item.Cells[(int) FileUploadIndex.AdverseEvents];
                        if (fileUpload != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                            }
                        }
                        break;
                    }
                    case "otherEvents":
                    {
                        TableCell editCell = e.Item.Cells[(int) Edit.OtherEvents];
                        if (editCell != null)
                        {
                            editCell.Visible = HasEditPermission;
                        }

                        TableCell remove = e.Item.Cells[(int) Remove.OtherEvents];
                        if (remove != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                                removeCheckBox.Enabled = true;
                                removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                            }
                        }

                        TableCell fileUpload = e.Item.Cells[(int) FileUploadIndex.OtherEvents];
                        if (fileUpload != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                            }
                        }
                        break;
                    }
                    case "triennialReviews":
                    {
                        TableCell editCell = e.Item.Cells[(int) Edit.triennialEvents];
                        if (editCell != null)
                        {
                            editCell.Visible = HasEditPermission;
                        }

                        TableCell remove = e.Item.Cells[(int) Remove.triennialEvents];
                        if (remove != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                CheckBox removeCheckBox = ((CheckBox) remove.Controls[1]);
                                removeCheckBox.Enabled = true;
                                removeCheckBox.Attributes.Add("onClick", "SaveCheckBoxState('" + removeCheckBox.ClientID + "', 'RemoveFlag')");
                            }
                        }
                        TableCell fileUpload = e.Item.Cells[(int) FileUploadIndex.triennialEvents];
                        if (fileUpload != null)
                        {
                            if (e.Item.ItemType == ListItemType.EditItem)
                            {
                                ((FileUpload) fileUpload.Controls[1]).Enabled = true;
                            }
                        }
                        break;
                    }
                }

                #endregion

                if (e.Item.ItemType == ListItemType.Header)
                {
// add Expand All/Collapse All Toggle Column Header

                    #region Header

                    // determine if there will be any expandable rows in this grid (i.e. whether any 
                    // Submissions have more than one review); if not, we don't want to provide the 
                    // "Toggle All" button
                    foreach (Review review in ((ArrayList) ((DataGrid) sender).DataSource))
                    {
                        if (review.Parent.ReviewCount > 1)
                        {
                            StatefulToggleButton image = new StatefulToggleButton(
                                ((DataGrid) sender).ID, e.Item.ItemIndex, pageCache);

                            if (e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls.Count == 0)
                            {
                                e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls.Add(image);
                                expanded = image.IsExpanded;
                            }
                            break;
                        }
                    }

                    #endregion
                }

                else if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem
                    || e.Item.ItemType == ListItemType.EditItem)
                {
                    /* handle displaying/hiding rows*/

                    string formsId = ((Review) e.Item.DataItem).FormsId;
                    // get the first one of this formsId
                    if (formsId != currentFormsId)
                    {
                        // update the tracker so we know what the subsequent rows should be compared to
                        currentFormsId = formsId;
                        e.Item.CssClass = "DataGridItem";
                        e.Item.Visible = true;
                        if (((Review) e.Item.DataItem).Parent.ReviewCount > 1)
                        {
                            StatefulToggleButton image = new StatefulToggleButton(
                                ((DataGrid) sender).ID, e.Item.ItemIndex, pageCache);

                            if (e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls.Count == 0)
                            {
                                e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls.Add(image);
                                expanded = image.IsExpanded;
                            }
                        }

                        ((Label) e.Item.Cells[(int) CommonCellIndexes.ParentRowIndicatorIndex].Controls[1]).
                            Text = true.ToString();

                        // Here depends on which datagrid is getting bound we need to check different Lable controls
                        // handle creation of Workflow report icon, javscript and assignment of the javascript
                        // to the button Testing for Workflow Report
                        //string dataGridID = ((DataGrid)sender).ID;

                        int processId = ((Review) e.Item.DataItem).ProtocolProcessId;
                        string ppId = processId.ToString();
                        if (processId > 0)
                        {
                            ImageButton viewImage = new ImageButton();
                            viewImage.ImageUrl = ViewImageURL;
                            //viewImage.CommandName = ViewApplicationCommand;
                            viewImage.OnClientClick = "javascript:window.open('../Research/ViewProtocolPage.aspx?Report=view&ProtocolProcessId=" + processId + "', 'ViewProtocolPage', 'resizable=yes, status=yes, scrollbars=yes');return false;";


                            ImageButton reportImage = new ImageButton();
                            reportImage.ImageUrl = ReportImageURL;
                            reportImage.Attributes["onclick"] =
                                string.Format("window.open('{0}?PPId={1}', 'WorkflowReport', '{2}');return false;",
                                    WorkFlowReportPage, ppId, PopUpFeatures);

                            switch (dataGridID)
                            {
                                case "continuingReviews":
                                case "annualReviews":
                                {
                                    e.Item.Cells[(int) WorkFlowReportIndex.ContinuingReviews].Controls.Add(reportImage);
                                    e.Item.Cells[(int) ViewApplicationIndex.ContinuingReviews].Controls.Add(viewImage);
                                }

                                    break;
                                case "triennialReviews":
                                    e.Item.Cells[(int) WorkFlowReportIndex.TriennialReviews].Controls.Add(reportImage);
                                    e.Item.Cells[(int) ViewApplicationIndex.TriennialReviews].Controls.Add(viewImage);
                                    break;
                                case "amendments":
                                {
                                    if (Protocol.ModuleType == Constants.ModuleType.Animals)
                                    {
                                        e.Item.Cells[(int) WorkFlowReportIndex.Amendments - 1].Controls.Add(reportImage);
                                        e.Item.Cells[(int) ViewApplicationIndex.Amendments - 1].Controls.Add(viewImage);
                                    }
                                    else
                                    {
                                        e.Item.Cells[(int) WorkFlowReportIndex.Amendments].Controls.Add(reportImage);
                                        e.Item.Cells[(int) ViewApplicationIndex.Amendments].Controls.Add(viewImage);
                                    }
                                }
                                    break;
                                case "adverseEvents":
                                {
                                    e.Item.Cells[(int) WorkFlowReportIndex.AdverseEvents].Controls.Add(reportImage);
                                    e.Item.Cells[(int) ViewApplicationIndex.AdverseEvents].Controls.Add(viewImage);
                                }
                                    break;
                                case "otherEvents":
                                {
                                    e.Item.Cells[(int) WorkFlowReportIndex.OtherEvents].Controls.Add(reportImage);
                                    e.Item.Cells[(int) ViewApplicationIndex.OtherEvents].Controls.Add(viewImage);
                                }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                        // now, get the other rows with this formsId and if the first one had its toggle button set to
                        // expanded, show it
                    else
                    {
                        e.Item.CssClass = "DataGridAlternatingItem";
                        if (!expanded)
                        {
                            e.Item.Visible = false;
                        }
                        ((Label) e.Item.Cells[(int) CommonCellIndexes.ParentRowIndicatorIndex].Controls[1]).
                            Text = false.ToString();
                    }

                    // handle creation of IRB notes icon, javscript and assignment of the javascript
                    // to the button
                    //if (((Humans.Review)e.Item.DataItem).Notification)
                    //{
                    ImageButton noteImage = new ImageButton();
                    noteImage.ImageUrl = ViewImageURL;
                    noteImage.CommandName = ViewIRBNotesCommand;

                    bool foundGrid = true;
                    int noteIndex = 0;
                    switch (((DataGrid) sender).ID)
                    {
                        case "continuingReviews":
                        case "annualReviews":
                            if (((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ReviewNotes].Controls[1]).Text == string.Empty ||
                                Convert.ToInt32(((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ReviewNotes].Controls[1]).Text) == 0)
                            {
                                foundGrid = false;
                            }
                            noteIndex = (int) NoteIndex.ContinuingReviews;
                            break;
                        case "amendments":
                            int amendmentIndex = (Protocol.ModuleType == Constants.ModuleType.Animals) ? ((int) NoteIndex.Amendments) - 1 : ((int) NoteIndex.Amendments);

                            if (((Label) e.Item.Cells[amendmentIndex].Controls[1]).Text == string.Empty ||
                                Convert.ToInt32(((Label) e.Item.Cells[amendmentIndex].Controls[1]).Text) == 0)
                            {
                                foundGrid = false;
                            }
                            noteIndex = (int) NoteIndex.Amendments;
                            if (Protocol.ModuleType == Constants.ModuleType.Animals)
                            {
                                noteIndex--;
                            }
                            break;
                        case "adverseEvents":
                            noteIndex = (int) NoteIndex.AdverseEvents;
                            if (((Label) e.Item.Cells[(int) NoteIndex.AdverseEvents].Controls[1]).Text == string.Empty ||
                                Convert.ToInt32(((Label) e.Item.Cells[(int) NoteIndex.AdverseEvents].Controls[1]).Text) == 0)
                            {
                                foundGrid = false;
                            }
                            break;
                        case "otherEvents":
                            noteIndex = (int) NoteIndex.OtherEvents;
                            if (((Label) e.Item.Cells[(int) NoteIndex.OtherEvents].Controls[1]).Text == string.Empty ||
                                Convert.ToInt32(((Label) e.Item.Cells[(int) NoteIndex.OtherEvents].Controls[1]).Text) == 0)
                            {
                                foundGrid = false;
                            }
                            break;
                        case "triennialReviews":
                            noteIndex = (int) NoteIndex.TriennialReview;
                            if (((Label) e.Item.Cells[(int) NoteIndex.TriennialReview].Controls[1]).Text == string.Empty ||
                                Convert.ToInt32(((Label) e.Item.Cells[(int) NoteIndex.TriennialReview].Controls[1]).Text) == 0)
                            {
                                foundGrid = false;
                            }
                            break;
                        default:
                            foundGrid = false;
                            break;
                    }
                    if (foundGrid)
                    {
                        e.Item.Cells[noteIndex].Controls.Add(noteImage);
                    }
                    //}

                    // disable view state for all but the first cell which is storing whether this item 
                    // is a parent row
                    for (int i = 1, cellCount = e.Item.Cells.Count; i < cellCount; ++i)
                    {
                        e.Item.Cells[i].EnableViewState = false;
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Hides/Shows child rows based on whether the expand/collapse button was clicked on the
        /// parent row
        /// </summary>
        /// <param name="source">dataGrid</param>
        /// <param name="e">imageButton +/- on the row</param>
        private void OnIRItemCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                if (e.CommandName == ToggleRowsCommand)
                {
                    StatefulToggleButton button =
                        (StatefulToggleButton) e.Item.Cells[(int) ReviewCellIndexes.PlusSignIndex].Controls[0];
                    button.ToggleExpandedState();

                    foreach (DataGridItem item in ((DataGrid) source).Items)
                    {
                        item.Visible = button.IsExpanded;
                    }

                    // the parent row's visibility may bave been turned off in the above conditional
                    // expression, so we need to make sure it's visible now
                    e.Item.Visible = true;
                }
                else if (e.CommandName == ViewIRBNotesCommand)
                {
                    Document doc = new Document(cachePolicy);
                    doc.Load(DataAccess.ConnectionString, Convert.ToInt32(((Label) e.Item.Cells[(int) ReviewCellIndexes.IRBNotes].Controls[1]).Text));

                    Hashtable outgoingData = new Hashtable();
                    outgoingData[Keys.DocumentKey] = doc;
                    //Script for popup window that displays the attachment
                    string script = "\n<script language=JavaScript id='DisplayAttachment'>\n" +
                        "window.open('DownloadForm.aspx', 'ViewFile', 'resizable=yes, status=yes, scrollbars=yes'); \n" +
                            "</script>";

                    if (!ClientScript.IsClientScriptBlockRegistered("DisplayAttachment"))
                    {
                        ClientScript.RegisterClientScriptBlock(GetType(), "DisplayAttachment", script);
                    }
                    pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                }
                else if (e.CommandName == ViewApplicationCommand)
                {
                    DisplayProcess(((DataGrid) source).DataKeys[e.Item.ItemIndex].ToString());
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Displays the ProtocolProcess associated with the passed
        /// protocolProcessID in a popup window in PDF form.
        /// </summary>
        /// <param name="protocolProcessId"></param>
        private void DisplayProcess(string protocolProcessId)
        {
            if (!string.IsNullOrEmpty(protocolProcessId))
            {
                ProtocolProcess protocolProcess =
                    ProtocolProcess.GetProtocolProcess(DataAccess.ConnectionString, Convert.ToInt32(protocolProcessId), cachePolicy, null);
                protocolProcess.Cache();

                string viewType;

                if (Constants.ProtocolProcessType.InitialReview == protocolProcess.Type ||
                    Constants.AnimalProtocolProcessType.InitialReview == protocolProcess.Type)
                {
                    ProtocolVersion protocolVersion = ((Application) protocolProcess).GetInitiallyApprovedVersion();
                    if (null != protocolVersion)
                    {
                        protocolVersion.Cache();
                    }
                    viewType = Constants.ViewApplicationType.FullUsingProtocolInformation;
                }
                else
                {
                    ProtocolVersion protocolVersion = cachePolicy.GetCachedObject(ProtocolVersion.ProtocolVersionKey) as ProtocolVersion;
                    if (null != protocolVersion)
                    {
                        protocolVersion.UnCache();
                    }
                    viewType = Constants.ViewApplicationType.Full;
                }

                DisplayProcessPopup(viewType);
            }
        }

        /// <summary>
        /// Displays the cached process in a popup in PDF form.
        /// 
        /// </summary>
        /// <param name="viewType"></param>
        private void DisplayProcessPopup(string viewType)
        {
            StringBuilder script = new StringBuilder();
            script.Append("\n<script language=JavaScript id='ViewProtocolPage'>\n");
            script.Append("var editorWin = null; \n");
            script.Append("editorWin = window.open('ViewProtocolPage.aspx?ViewApplicationType=" + viewType + "', 'ViewProtocolPage', 'width=800, height=600, status=yes, toolbar=no, resizable=yes'); \n");
            script.Append("</script>");
            if (!ClientScript.IsClientScriptBlockRegistered("ViewProtocolPage"))
            {
                ClientScript.RegisterClientScriptBlock(GetType(), "ViewProtocolPage", script.ToString());
            }
        }

        /// <summary>
        /// Hides/Shows child rows based on whether the expand/collapse button was clicked on the
        /// parent row; Also handles hiding or collapsing all rows based on the command from the
        /// header
        /// </summary>
        /// <param name="source">dataGrid</param>
        /// <param name="e">imageButton +/- on the row</param>
        private void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                if (e.CommandName == ToggleRowsCommand)
                {
                    StatefulToggleButton button =
                        (StatefulToggleButton) e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls[0];
                    button.ToggleExpandedState();

                    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                    {
                        string formsId = e.Item.Cells[(int) CommonCellIndexes.FormsIdIndex].Text;

                        foreach (DataGridItem item in ((DataGrid) source).Items)
                        {
                            // determine if this is a child row of the row that raised the toggle event
                            if (item.Cells[(int) CommonCellIndexes.FormsIdIndex].Text == formsId)
                            {
                                item.Visible = button.IsExpanded;
                            }
                        }

                        // the parent row's visibility may bave been turned off in the above conditional
                        // expression, so we need to make sure it's visible now
                        e.Item.Visible = true;
                    }
                    else if (e.Item.ItemType == ListItemType.Header)
                    {
                        // show (or collapse) all rows in the grid, and expand (or collapse)
                        // all StatefulToggleButtons

                        bool isExpanded = ((StatefulToggleButton)
                            e.Item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls[0]).IsExpanded;

                        foreach (DataGridItem item in ((DataGrid) source).Items)
                        {
                            item.Visible = isExpanded;

                            ControlCollection controls = item.Cells[(int) CommonCellIndexes.PlusSignIndex].Controls;
                            if (controls.Count > 0)
                            {
                                StatefulToggleButton toggler = (StatefulToggleButton) controls[0];
                                if (toggler.IsExpanded != isExpanded)
                                {
                                    toggler.ToggleExpandedState();
                                }

                                // if the controls.Count > 0, this means there was a toggler on the row,
                                // which means it has children, and these top-level rows should not be hidden 
                                item.Visible = true;
                            }
                            else
                            {
                                // always show the top-level rows (the ones that don't have children rows won't pass
                                // the previous if condition)
                                if (((Label) item.Cells[(int) CommonCellIndexes.ParentRowIndicatorIndex].
                                    Controls[1]).Text.Equals(true.ToString()))
                                {
                                    item.Visible = true;
                                }
                            }
                        }
                    }
                }
                else if (e.CommandName == ViewIRBNotesCommand)
                {
                    Document doc = new Document(cachePolicy);
                    int boardReviewId = 0;
                    switch (((DataGrid) source).ID)
                    {
                        case "amendments":
                        {
                            boardReviewId = Convert.ToInt32(((Label) e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) AmendmentCellIndexes.ReviewNotes - 1 : (int) AmendmentCellIndexes.ReviewNotes].Controls[1]).Text);
                            break;
                        }
                        case "continuingReviews":
                        case "annualReviews":
                        {
                            boardReviewId = Convert.ToInt32(((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ReviewNotes].Controls[1]).Text);
                            break;
                        }
                        case "adverseEvents":
                        {
                            boardReviewId = Convert.ToInt32(((Label) e.Item.Cells[((int) ReviewCellIndexes.IRBNotes) + 1].Controls[1]).Text);
                            break;
                        }
                        case "otherEvents":
                        {
                            boardReviewId = Convert.ToInt32(((Label) e.Item.Cells[((int) ReviewCellIndexes.IRBNotes) + 2].Controls[1]).Text);
                            break;
                        }
                        case "triennialReviews":
                        {
                            boardReviewId = Convert.ToInt32(((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ReviewNotes].Controls[1]).Text);
                            break;
                        }
                    }
                    if (boardReviewId != 0)
                    {
                        doc.Load(DataAccess.ConnectionString, boardReviewId);

                        Hashtable outgoingData = new Hashtable();
                        outgoingData[Keys.DocumentKey] = doc;
                        //Script for popup window that displays the attachment
                        string script = "\n<script language=JavaScript id='DisplayAttachment'>\n" +
                            "window.open('DownloadForm.aspx', 'ViewFile', 'resizable=yes, status=yes, scrollbars=yes'); \n" +
                                "</script>";

                        if (!ClientScript.IsClientScriptBlockRegistered("DisplayAttachment"))
                        {
                            ClientScript.RegisterClientScriptBlock(GetType(), "DisplayAttachment", script);
                        }
                        pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                    }
                    else
                    {
                        throw new Exception("The unique id of this board review could not be found");
                    }
                }
                else if (e.CommandName == ViewApplicationCommand)
                {
                    DisplayProcess(((DataGrid) source).DataKeys[e.Item.ItemIndex].ToString());
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = AnnunciatorTitle;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }

        /// <summary>
        /// Resets the subnavigation selected link before the breadCrumb performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                humansSubModNavigation.Reset();
                animalsSubModNavigation.Reset();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Constructs and caches a hashtable of data for use by the page to which nagivation leads
        /// </summary>
        private void ProcessNavigation()
        {
            try
            {
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ProtocolIdKey, pageCache[CachedProtocolIdKey]);
                outgoingData.Add(Keys.ProtocolProcessIdKey, pageCache[Keys.ProtocolProcessIdKey]);
                outgoingData.Add(Keys.ProtocolAccessKey, pageCache[Keys.ProtocolAccessKey]);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link before the header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                ProcessNavigation();
                humansSubModNavigation.Reset();
                animalsSubModNavigation.Reset();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link before the header performs a redirect.
        /// </summary>
        private void OnHumansSubModNavigate()
        {
            try
            {
                ProcessNavigation();
                humansSubModNavigation.Reset();
                animalsSubModNavigation.Reset();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// If the current protocol is not a legacy protocol, then locks the process if it is unlocked and vice-versa.
        /// If the current protocol is a legacy protocol, then locks the protocol if it is unlocked and vice-versa.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnToggleProtocolLockClick(object sender, EventArgs e)
        {
            try
            {
                InsightServiceUtility.DocumentUtility docUtil = new InsightServiceUtility.DocumentUtility();
                if (ProtocolProcess != null)
                {
                    if (ProtocolProcess.Locked)
                    {
                        ProtocolProcess.Unlock(DataAccess.ConnectionString, cachePolicy, Protocol);
                        /*Trackit 10114: On  unlock delete the frozen PDFs */
                        docUtil.DeleteViewAppDocuments(ProtocolProcess.Id, ProtocolProcess.ProtocolId);
                    }
                    else
                    {
                        ProtocolProcess.Lock(DataAccess.ConnectionString, cachePolicy, Protocol);
                        // call submit on the process also, to update any info that may have changed.
                        // note that for amendments, we don't call submit....???
                        if (!ProtocolProcess.Name.Contains("Prog"))
                        {
                            DirectoryInfo directoryInfo = new DirectoryInfo(Server.MapPath("~/bin"));

                            RexParams rexParameters = null;
                            if (Protocol.ModuleType == Constants.ModuleType.Humans)
                            {
                                rexParameters = new RexParams();
                            }
                            else if (Protocol.ModuleType == Constants.ModuleType.Animals)
                            {
                                rexParameters = new AnimalsRexParams();
                            }

                            ProtocolProcess.Submit(cachePolicy, DataAccess.GetConnectionString(),
                                DataAccess.GetConnectionString("Rex"),
                                string.Format("{0}\\", directoryInfo.FullName), rexParameters,
                                true);
                        }

                        /*Make an asynchronous call to the InsightUtility web service to generate and freeze the VFA document
						 Trackit # 9298*/
                        string docStageFolderEntry = Settings.GetKeyValue("DocumentStagingFolder", "DocumentStagingFolder");
                        string docStagingFolder = string.Format(@"\\{0}",
                            Path.Combine(HttpContext.Current.Server.MachineName, docStageFolderEntry));

                        //For local testing in dev environment
                        //string docStagingFolder = @"\\phsweb418\DocumentStagingFolder";

                        /*GenerateAndSaveApplicationDocuments is an ASYNC (one-way) call on DocumentUtility web service
                             * that will generate and store the application documents (VFA, VA, CV, IR) to SharePoint
                             It will OVERWRITE any existing documents on SharePoint. DeleteDocuments is not called to improve performance
                             */
                        docUtil.GenerateAndSaveApplicationDocuments(ProtocolProcess.Id, docStagingFolder, ProtocolProcess.ProtocolId);
                    }
                    SetLockUnlockButton(ProtocolProcess.Locked);
                }
                else
                {
                    Protocol.IsLocked = !Protocol.IsLocked;
                    Protocol.Save(DataAccess.ConnectionString);

                    SetLockUnlockButton(Protocol.IsLocked);
                }
                //Reload the page so as to reload the navigation controls.
                Response.Redirect("ProtocolDetails.aspx", false);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region GridToggle Event Handlers

        /// <summary>
        /// Toggles the visibility of the panel containing the Initial Reviews, and 
        /// rebinds all grids on the page so the dynamically added controls in the grid
        /// will get re-created
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnIRClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                IRExpanded = !IRExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        private void OnCRClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                CRExpanded = !CRExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        private void OnTRClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                TRExpanded = !TRExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        private void OnAMClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                AMExpanded = !AMExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        private void OnAEClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                AEExpanded = !AEExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        private void OnOEClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                OEExpanded = !OEExpanded;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Private Helper Methods

        /// <summary>
        /// Resets the hash table that stores page data, and also the cachedProtocolId, 
        /// which indicate which protocol the cached page data is based on
        /// </summary>
        private void UnCachePageData()
        {
            pageCachePolicy.UnCache(CachedProtocolIdKey);

            pageCache = new Hashtable();
            pageCachePolicy.Cache(PageCacheKey, pageCache);
        }

        /// <summary>
        /// Pulls the arraylists out of the page's cache and binds them to the appropriate grids
        /// </summary>
        private void BindGrids()
        {
            initialReview.DataKeyField = continuingReviews.DataKeyField = amendments.DataKeyField =
                otherEvents.DataKeyField = adverseEvents.DataKeyField = "ProtocolProcessId";

            initialReview.DataSource = pageCache[InitialReviewsKey] as ArrayList;
            initialReview.DataBind();

            continuingReviews.DataSource = pageCache[ContinuingReviewsKey] as ArrayList;
            continuingReviews.DataBind();

            amendments.DataSource = pageCache[AmendmentsReviewsKey] as ArrayList;
            amendments.DataBind();

            adverseEvents.DataSource = pageCache[AdverseEventReviewsKey] as ArrayList;
            adverseEvents.DataBind();

            if (Protocol.ModuleType == Constants.ModuleType.Animals)
            {
                triennialReviews.DataSource = pageCache[TriennialReviewsKey] as ArrayList;
                triennialReviews.DataBind();
            }
            else
            {
                otherEvents.DataSource = pageCache[OtherEventReviewsKey] as ArrayList;
                otherEvents.DataBind();
            }
        }


        private void SetLockUnlockButton(bool isLocked)
        {
            if (isLocked)
            {
                toggleProtocolLock.Text = ToggleLockStatusTextWhenLocked;
                toggleProtocolLock.BackColor = ColorTranslator.FromHtml("#cacaca");
                toggleProtocolLock.Attributes.Add("onclick", "return confirm('Do you really want to Unlock the protocol?');");
            }
            else
            {
                toggleProtocolLock.Text = ToggleLockStatusTextWhenUnlocked;
                toggleProtocolLock.BackColor = Color.Red;
                toggleProtocolLock.Attributes.Add("onclick", "return confirm('Do you really want to Lock the protocol?');");
            }
        }

        #endregion

        #region Private Methods - Grid Loaders

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.  Note
        /// that there will always be at least one row in this grid, so we don't need to check whether the
        /// count of rows = 0
        /// </summary>
        private void LoadIRGrid()
        {
            ArrayList reviews = pageCache[InitialReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy,
                    (Protocol.ModuleType == Constants.ModuleType.Animals) ? Submissions.SubmissionType.AnimalsIR : Submissions.SubmissionType.InitialReview);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());
                reviews = new ArrayList();
                string submissionStatus = string.Empty;

                // count down because we want the ids to appear in descending order on the page
                int irCount = subList.Count;

                for (int i = irCount - 1; i >= 0; --i)
                {
                    ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();
                    for (int j = 0; j < revList.Count; ++j)
                    {
                        reviews.Add(revList[j]);
                        // get the status of the most recent review to display on 
                        // the top of the grid
                        if (j == 0)
                        {
                            submissionStatus = ((Review) revList[j]).Status;
                        }
                    }
                }

                pageCache[InitialReviewsKey] = reviews;
                pageCache[IRGridStatusKey] = submissionStatus;
                pageCachePolicy.Cache(PageCacheKey, pageCache);
                irContainerStatus.Text = submissionStatus;
                initialReviewToggler.Visible = (irCount > 0);
            }
            else
            {
                irContainerStatus.Text = (string) pageCache[IRGridStatusKey];
                initialReviewToggler.Visible = (reviews.Count > 0);
            }
        }

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.
        /// </summary>
        private void LoadCRGrid()
        {
            ArrayList reviews = pageCache[ContinuingReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy,
                    (Protocol.ModuleType == Constants.ModuleType.Animals) ? Submissions.SubmissionType.AnnualReview : Submissions.SubmissionType.ContinuingReview);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());

                // this number gets displayed on a label at the top of the grid
                int numberPending = 0;
                if (subList.Count > 0)
                {
                    reviews = new ArrayList();

                    // count down because we want the ids to appear in descending order on the page
                    for (int i = subList.Count - 1; i >= 0; --i)
                    {
                        ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();

                        string status = ((Submission) subList.GetByIndex(i)).Status;
                        if (status.Equals(PendingStatus) || status.Equals(DeferredStatus) ||
                            status.Equals(ReqModStatus) || status.Equals(HoldStatus))
                        {
                            ++numberPending;
                        }

                        for (int j = 0; j < revList.Count; ++j)
                        {
                            reviews.Add(revList[j]);
                        }
                    }

                    crNumberTotal.Text = subs.TotalCount.ToString();
                    crNumberPending.Text = numberPending.ToString();
                }
                else
                {
                    crNumberTotal.Text = NoRecordsDisplay;
                    crNumberPending.Text = NoRecordsDisplay;
                    crToggle.Visible = false;
                }

                pageCache[ContinuingReviewsKey] = reviews;
                pageCache[NumberCRPendingKey] = numberPending.ToString();
                pageCache[CRSubCountKey] = subs.TotalCount.ToString();
                pageCachePolicy.Cache(PageCacheKey, pageCache);
            }
            else
            {
                if (reviews.Count > 0)
                {
                    crNumberTotal.Text = (string) pageCache[CRSubCountKey];
                    crNumberPending.Text = (string) pageCache[NumberCRPendingKey];
                }

                else
                {
                    crNumberTotal.Text = NoRecordsDisplay;
                    crNumberPending.Text = NoRecordsDisplay;
                    crToggle.Visible = false;
                }
            }
        }

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.
        /// </summary>
        private void LoadTRGrid()
        {
            ArrayList reviews = pageCache[TriennialReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy, Submissions.SubmissionType.TriennialReview);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());

                // this number gets displayed on a label at the top of the grid
                int numberPending = 0;
                if (subList.Count > 0)
                {
                    reviews = new ArrayList();

                    // count down because we want the ids to appear in descending order on the page
                    for (int i = subList.Count - 1; i >= 0; --i)
                    {
                        ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();

                        string status = ((Submission) subList.GetByIndex(i)).Status;
                        if (status.Equals(PendingStatus) || status.Equals(DeferredStatus) ||
                            status.Equals(ReqModStatus) || status.Equals(HoldStatus))
                        {
                            ++numberPending;
                        }

                        for (int j = 0; j < revList.Count; ++j)
                        {
                            reviews.Add(revList[j]);
                        }
                    }

                    trNumberTotal.Text = subs.TotalCount.ToString();
                    trNumberPending.Text = numberPending.ToString();
                }
                else
                {
                    trNumberTotal.Text = NoRecordsDisplay;
                    trNumberPending.Text = NoRecordsDisplay;
                    trToggle.Visible = false;
                }

                pageCache[TriennialReviewsKey] = reviews;
                pageCache[NumberTRPendingKey] = numberPending.ToString();
                pageCache[TRSubCountKey] = subs.TotalCount.ToString();
                pageCachePolicy.Cache(PageCacheKey, pageCache);
            }
            else
            {
                if (reviews.Count > 0)
                {
                    trNumberTotal.Text = (string) pageCache[TRSubCountKey];
                    trNumberPending.Text = (string) pageCache[NumberTRPendingKey];
                }

                else
                {
                    trNumberTotal.Text = NoRecordsDisplay;
                    trNumberPending.Text = NoRecordsDisplay;
                    trToggle.Visible = false;
                }
            }
        }

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.
        /// </summary>
        private void LoadAmendmentsGrid()
        {
            ArrayList reviews = pageCache[AmendmentsReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy, Submissions.SubmissionType.Amendment);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());

                // this number gets displayed on a label at the top of the grid
                int numberPending = 0;
                if (subList.Count > 0)
                {
                    reviews = new ArrayList();

                    // count down because we want the ids to appear in descending order on the page
                    for (int i = subList.Count - 1; i >= 0; --i)
                    {
                        ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();

                        string status = ((Submission) subList.GetByIndex(i)).Status;
                        if (status.Equals(PendingStatus) || status.Equals(DeferredStatus) ||
                            status.Equals(ReqModStatus) || status.Equals(HoldStatus))
                        {
                            ++numberPending;
                        }

                        for (int j = 0; j < revList.Count; ++j)
                        {
                            reviews.Add(revList[j]);
                        }
                    }

                    amNumberTotal.Text = subs.TotalCount.ToString();
                    amNumberPending.Text = numberPending.ToString();
                }
                else
                {
                    amNumberTotal.Text = amNumberPending.Text = NoRecordsDisplay;
                    amToggler.Visible = false;
                }

                pageCache[AmendmentsReviewsKey] = reviews;
                pageCache[AMSubCountKey] = subs.TotalCount.ToString();
                pageCache[NumberAMPendingKey] = numberPending.ToString();
                pageCachePolicy.Cache(PageCacheKey, pageCache);
            }

            else
            {
                if (reviews.Count > 0)
                {
                    amNumberTotal.Text = (string) pageCache[AMSubCountKey];
                    amNumberPending.Text = (string) pageCache[NumberAMPendingKey];
                }
                else
                {
                    amNumberTotal.Text = amNumberPending.Text = NoRecordsDisplay;
                    amToggler.Visible = false;
                }
            }
        }

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.
        /// </summary>
        private void LoadAEGrid()
        {
            ArrayList reviews = pageCache[AdverseEventReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy,
                    (Protocol.ModuleType == Constants.ModuleType.Animals) ? Submissions.SubmissionType.Deficiency : Submissions.SubmissionType.AdverseEvent);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                string pendingCount = string.Empty;
                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());
                if (subList.Count > 0)
                {
                    // this number gets displayed on a label at the top of the grid
                    int numberPending = 0;

                    reviews = new ArrayList();

                    // count down because we want the ids to appear in descending order on the page
                    for (int i = subList.Count - 1; i >= 0; --i)
                    {
                        ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();

                        string status = ((Submission) subList.GetByIndex(i)).Status;
                        if (status.Equals(PendingStatus) || status.Equals(DeferredStatus) ||
                            status.Equals(ReqModStatus) || status.Equals(HoldStatus))
                        {
                            ++numberPending;
                        }

                        for (int j = 0; j < revList.Count; ++j)
                        {
                            reviews.Add(revList[j]);
                        }
                    }

                    aeNumberTotal.Text = subs.TotalCount.ToString();
                    pendingCount = numberPending.ToString();
                    aeNumberPending.Text = pendingCount;
                }
                else
                {
                    aeNumberTotal.Text = NoRecordsDisplay;
                    aeNumberPending.Text = NoRecordsDisplay;
                    aeToggler.Visible = false;
                }
                pageCache[AdverseEventReviewsKey] = reviews;
                pageCache[AdvEvSubCountKey] = subs.TotalCount.ToString();
                pageCache[NumberAdvEvPendingKey] = pendingCount;
                pageCachePolicy.Cache(PageCacheKey, pageCache);
            }

            else
            {
                if (reviews.Count > 0)
                {
                    aeNumberTotal.Text = (string) pageCache[AdvEvSubCountKey];
                    aeNumberPending.Text = (string) pageCache[NumberAdvEvPendingKey];
                }

                else
                {
                    aeNumberTotal.Text = NoRecordsDisplay;
                    aeNumberPending.Text = NoRecordsDisplay;
                    aeToggler.Visible = false;
                }
            }
        }

        /// <summary>
        /// Checks whether the reviews for the grid are in the page's cache.  If they're not, the
        /// reviews are created and stored in the page's cache.  Labels that appear on the top of the grid
        /// are also set here, and after they're determined, they are also stored in the page's cache.
        /// </summary>
        private void LoadOEGrid()
        {
            ArrayList reviews = pageCache[OtherEventReviewsKey] as ArrayList;
            if (reviews == null)
            {
                Submissions subs = new Submissions(cachePolicy, Submissions.SubmissionType.OtherEvent);
                subs.Load(
                    DataAccess.GetConnectionString(),
                    protocolId);

                SortedList subList = subs.GetSubmissionList(DataAccess.GetConnectionString());
                // this number gets displayed on a label at the top of the grid
                int numberPending = 0;
                if (subList.Count > 0)
                {
                    reviews = new ArrayList();

                    // count down because we want the ids to appear in descending order on the page
                    for (int i = subList.Count - 1; i >= 0; --i)
                    {
                        ArrayList revList = ((Submission) subList.GetByIndex(i)).GetBoardReviewsList();

                        string status = ((Submission) subList.GetByIndex(i)).Status;
                        if (status.Equals(PendingStatus) || status.Equals(DeferredStatus) ||
                            status.Equals(ReqModStatus) || status.Equals(HoldStatus))
                        {
                            ++numberPending;
                        }

                        for (int j = 0; j < revList.Count; ++j)
                        {
                            reviews.Add(revList[j]);
                        }
                    }
                    oeNumberTotal.Text = subs.TotalCount.ToString();
                    oeNumberPending.Text = numberPending.ToString();
                }

                else
                {
                    oeNumberTotal.Text = oeNumberPending.Text = NoRecordsDisplay;
                    oeToggler.Visible = false;
                }

                pageCache[OtherEventReviewsKey] = reviews;
                pageCache[OESubCountKey] = subs.TotalCount.ToString();
                pageCache[NumberOEPendingKey] = numberPending.ToString();
                pageCachePolicy.Cache(PageCacheKey, pageCache);
            }
            else
            {
                if (reviews.Count > 0)
                {
                    oeNumberTotal.Text = (string) pageCache[OESubCountKey];
                    oeNumberPending.Text = (string) pageCache[NumberOEPendingKey];
                }
                else
                {
                    oeNumberTotal.Text = oeNumberPending.Text = NoRecordsDisplay;
                    oeToggler.Visible = false;
                }
            }
        }

        private void ResetHiddenField()
        {
            ClientScript.RegisterStartupScript(GetType(), "ResetHiddenField", string.Format(
                "<script language='javascript'>\n" +
                    "function ResetHiddenField()\n" +
                        "{{\n" +
                            "\tvar hiddenField = document.getElementsByName('{0}');\n" +
                                "\tif (hiddenField != null)\n" +
                                    "\t\thiddenField(0).value = 'False';\n" +
                                        "}}\n" +
                                            "ResetHiddenField(); \n" +
                                                "</script>", RemoveFlag));
        }

        /// <summary>
        /// Scans & Saves the posted file as a blob, settinng the appropriate mapping for the saved document.
        /// </summary>
        /// <param name="postedFile">File seected</param>
        /// <param name="protocolProcessId">ProcessId</param>
        /// <returns></returns>
        private void ScanAndSaveNotificationLetters(HttpPostedFile postedFile, int protocolProcessId, int boardReviewId, string boardStatus, string protocolNumber, int documentId)
        {
            if (postedFile.ContentLength > 0)
            {
                //store uploaded files in a temporary location and do a virus scan  
                string filePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());

                postedFile.SaveAs(filePath);

                bool isClean = true;
                if (bool.Parse(Settings.GetKeyValue("VirusScanner.Enable", "false")))
                {
                    try
                    {
                        Document.ScanFileForVirus(filePath);
                    }
                    catch
                    {
                        isClean = false;
                    }
                }
                //Create the byte stream of the uploaded file
                if (isClean)
                {
                    FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read);
                    byte[] data = new byte[fs.Length];
                    fs.Read(data, 0, Convert.ToInt32(fs.Length));
                    fs.Close();
                    Document doc = new Document(cachePolicy);
                    if (documentId > 0)
                    {
                        //Load the already existing documentId for update
                        doc.Load(DataAccess.ConnectionString, Convert.ToInt32(documentId));
                    }
                    doc.Blob = data;
                    doc.Name = postedFile.FileName;
                    doc.Save(DataAccess.ConnectionString);
                    doc.SaveFile(DataAccess.ConnectionString);

                    //Save the newly created mapping
                    UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    ProtocolManager.SaveNotificationLetter(
                        protocolProcessId
                        , boardReviewId
                        , boardStatus
                        , doc.Id
                        , userContext.PersonId
                        , DataAccess.ConnectionString
                        , protocolNumber);
                }
            }
        }

        #region Cancel command event handler

        /// <summary>
        /// Sets the index of the item being edited and refreshes the staff grid
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnGridCancel(object source, DataGridCommandEventArgs e)
        {
            try
            {
                annunciator.Message = string.Empty;
                string dataGridID = ((DataGrid) source).ID;
                switch (dataGridID)
                {
                    case "initialReview":
                    {
                        initialReview.EditItemIndex = -1;
                        pageCache[InitialReviewsKey] = null;
                        LoadIRGrid();
                        break;
                    }
                    case "amendments":
                    {
                        amendments.EditItemIndex = -1;
                        pageCache[AmendmentsReviewsKey] = null;
                        LoadAmendmentsGrid();
                        break;
                    }
                    case "continuingReviews":
                    case "annualReviews":
                    {
                        continuingReviews.EditItemIndex = -1;
                        pageCache[ContinuingReviewsKey] = null;
                        LoadCRGrid();
                        break;
                    }
                    case "triennialReviews":
                    {
                        triennialReviews.EditItemIndex = -1;
                        pageCache[TriennialReviewsKey] = null;
                        LoadTRGrid();
                        break;
                    }
                    case "adverseEvents":
                    {
                        adverseEvents.EditItemIndex = -1;
                        pageCache[AdverseEventReviewsKey] = null;
                        LoadAEGrid();
                        break;
                    }
                    case "otherEvents":
                    {
                        otherEvents.EditItemIndex = -1;
                        pageCache[OtherEventReviewsKey] = null;
                        LoadOEGrid();
                        break;
                    }
                }
                boundFirstIR = false;
                currentFormsId = string.Empty;
                BindGrids();
                ResetHiddenField();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Grid Edit Command event handler

        /// <summary>
        /// Sets the index of the item being edited and refreshes the IR grid
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnGridEdit(object source, DataGridCommandEventArgs e)
        {
            try
            {
                string dataGridID = ((DataGrid) source).ID;
                switch (dataGridID)
                {
                        //Only one grid should be editable at any istant and so check if there exists a grid in edit mode
                    case "initialReview":
                    {
                        if (initialReview.EditItemIndex > -1 ||
                            (amendments.EditItemIndex > -1 ||
                                adverseEvents.EditItemIndex > -1 ||
                                    otherEvents.EditItemIndex > -1 ||
                                        triennialReviews.EditItemIndex > -1 ||
                                            continuingReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        initialReview.EditItemIndex = e.Item.ItemIndex;
                        break;
                    }
                    case "amendments":
                    {
                        if (amendments.EditItemIndex > -1 ||
                            (initialReview.EditItemIndex > -1 ||
                                adverseEvents.EditItemIndex > -1 ||
                                    otherEvents.EditItemIndex > -1 ||
                                        triennialReviews.EditItemIndex > -1 ||
                                            continuingReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        amendments.EditItemIndex = e.Item.ItemIndex;
                        LoadAmendmentsGrid();
                        break;
                    }

                    case "adverseEvents":
                    {
                        if (adverseEvents.EditItemIndex > -1 ||
                            (initialReview.EditItemIndex > -1 ||
                                amendments.EditItemIndex > -1 ||
                                    otherEvents.EditItemIndex > -1 ||
                                        triennialReviews.EditItemIndex > -1 ||
                                            continuingReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        adverseEvents.EditItemIndex = e.Item.ItemIndex;
                        LoadAEGrid();
                        break;
                    }
                    case "otherEvents":
                    {
                        if (otherEvents.EditItemIndex > -1 ||
                            (initialReview.EditItemIndex > -1 ||
                                amendments.EditItemIndex > -1 ||
                                    adverseEvents.EditItemIndex > -1 ||
                                        triennialReviews.EditItemIndex > -1 ||
                                            continuingReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        otherEvents.EditItemIndex = e.Item.ItemIndex;
                        LoadOEGrid();
                        break;
                    }
                    case "triennialReviews":
                    {
                        if (triennialReviews.EditItemIndex > -1 ||
                            (initialReview.EditItemIndex > -1 ||
                                amendments.EditItemIndex > -1 ||
                                    adverseEvents.EditItemIndex > -1 ||
                                        otherEvents.EditItemIndex > -1 ||
                                            continuingReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        triennialReviews.EditItemIndex = e.Item.ItemIndex;
                        LoadTRGrid();
                        break;
                    }
                    case "continuingReviews":
                    case "annualReviews":
                    {
                        if (continuingReviews.EditItemIndex > -1 ||
                            (initialReview.EditItemIndex > -1 ||
                                amendments.EditItemIndex > -1 ||
                                    adverseEvents.EditItemIndex > -1 ||
                                        otherEvents.EditItemIndex > -1 ||
                                            triennialReviews.EditItemIndex > -1))
                        {
                            annunciator.Message = "Please Save / Cancel the current trasaction to be able to proceed";
                            return;
                        }
                        continuingReviews.EditItemIndex = e.Item.ItemIndex;
                        LoadCRGrid();
                        break;
                    }
                }
                LoadIRGrid();
                currentFormsId = string.Empty;
                boundFirstIR = false;
                BindGrids();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Grid PreRender event

        /// <summary>
        /// Sets the index of the item being edited and refreshes the grid
        /// </summary>
        /// <param name="sender">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnGridPreRender(object sender, EventArgs e)
        {
            try
            {
                if (initialReview.EditItemIndex > -1)
                {
                    initialReview.Columns[(int) Remove.InitialReview].Visible =
                        initialReview.Columns[(int) FileUploadIndex.InitialReview].Visible = true;
                }
                else
                {
                    initialReview.Columns[(int) Remove.InitialReview].Visible =
                        initialReview.Columns[(int) FileUploadIndex.InitialReview].Visible = false;
                }

                if (amendments.EditItemIndex > -1)
                {
                    amendments.Columns[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) Remove.Amendments - 1 : (int) Remove.Amendments].Visible =
                        amendments.Columns[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) FileUploadIndex.Amendments - 1 : (int) FileUploadIndex.Amendments].Visible = true;
                }
                else
                {
                    amendments.Columns[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) Remove.Amendments - 1 : (int) Remove.Amendments].Visible =
                        amendments.Columns[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) FileUploadIndex.Amendments - 1 : (int) FileUploadIndex.Amendments].Visible = false;
                }

                if (triennialReviews.EditItemIndex > -1)
                {
                    triennialReviews.Columns[(int) Remove.triennialEvents].Visible =
                        triennialReviews.Columns[(int) FileUploadIndex.triennialEvents].Visible = true;
                }
                else
                {
                    triennialReviews.Columns[(int) Remove.triennialEvents].Visible =
                        triennialReviews.Columns[(int) FileUploadIndex.triennialEvents].Visible = false;
                }

                if (continuingReviews.EditItemIndex > -1)
                {
                    continuingReviews.Columns[(int) Remove.ContinuingReviews].Visible =
                        continuingReviews.Columns[(int) FileUploadIndex.ContinuingReviews].Visible = true;
                }
                else
                {
                    continuingReviews.Columns[(int) Remove.ContinuingReviews].Visible =
                        continuingReviews.Columns[(int) FileUploadIndex.ContinuingReviews].Visible = false;
                }

                if (adverseEvents.EditItemIndex > -1)
                {
                    adverseEvents.Columns[(int) Remove.AdverseEvents].Visible =
                        adverseEvents.Columns[(int) FileUploadIndex.AdverseEvents].Visible = true;
                }
                else
                {
                    adverseEvents.Columns[(int) Remove.AdverseEvents].Visible =
                        adverseEvents.Columns[(int) FileUploadIndex.AdverseEvents].Visible = false;
                }

                if (otherEvents.EditItemIndex > -1)
                {
                    otherEvents.Columns[(int) Remove.OtherEvents].Visible =
                        otherEvents.Columns[(int) FileUploadIndex.OtherEvents].Visible = true;
                }
                else
                {
                    otherEvents.Columns[(int) Remove.OtherEvents].Visible =
                        otherEvents.Columns[(int) FileUploadIndex.OtherEvents].Visible = false;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Grid Update command event handler

        /// <summary>
        /// Sets the index of the item being edited and refreshes the grids
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnGridUpdate(object source, DataGridCommandEventArgs e)
        {
            try
            {
                string dataGridID = ((DataGrid) source).ID;
                string protocolProcessId;
                string boardReviewId;
                string boardStatus;
                string notificationLetterId;

                switch (dataGridID)
                {
                    case "initialReview":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[(int) ReviewCellIndexes.ProtocolProcessId].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[(int) ReviewCellIndexes.BoardReviewId].Controls[0]).Text;
                        boardStatus = e.Item.Cells[(int) ReviewCellIndexes.Status].Text;
                        notificationLetterId = ((Label) e.Item.Cells[(int) ReviewCellIndexes.IRBNotes].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(int) FileUploadIndex.InitialReview].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        initialReview.EditItemIndex = -1;
                        pageCache[InitialReviewsKey] = null;
                        break;
                    }

                    case "amendments":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) AmendmentCellIndexes.ProtocolProcessId - 1 : (int) AmendmentCellIndexes.ProtocolProcessId].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) BoardReviewIdIndex.Amendments - 1 : (int) BoardReviewIdIndex.Amendments].Controls[0]).Text;
                        boardStatus = e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) AmendmentCellIndexes.Status - 1 : (int) AmendmentCellIndexes.Status].Text;
                        notificationLetterId = ((Label) e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) AmendmentCellIndexes.ReviewNotes - 1 : (int) AmendmentCellIndexes.ReviewNotes].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(Protocol.ModuleType == Constants.ModuleType.Animals) ? (int) FileUploadIndex.Amendments - 1 : (int) FileUploadIndex.Amendments].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        amendments.EditItemIndex = -1;
                        pageCache[AmendmentsReviewsKey] = null;
                        LoadAmendmentsGrid();
                        break;
                    }

                    case "triennialReviews":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.ProtocolProcessId) + 3].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[(int) BoardReviewIdIndex.triennialEvents].Controls[0]).Text;
                        boardStatus = e.Item.Cells[((int) ReviewCellIndexes.Status) + 3].Text;
                        notificationLetterId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.IRBNotes) + 3].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(int) FileUploadIndex.triennialEvents].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        triennialReviews.EditItemIndex = -1;
                        pageCache[TriennialReviewsKey] = null;
                        LoadTRGrid();
                        break;
                    }
                    case "continuingReviews":
                    case "annualReviews":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ProtocolProcessId].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[(int) BoardReviewIdIndex.ContinuingReviews].Controls[0]).Text;
                        boardStatus = e.Item.Cells[(int) ContinuingReviewCellIndexes.Status].Text;
                        notificationLetterId = ((Label) e.Item.Cells[(int) ContinuingReviewCellIndexes.ReviewNotes].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(int) FileUploadIndex.ContinuingReviews].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        continuingReviews.EditItemIndex = -1;
                        pageCache[ContinuingReviewsKey] = null;
                        LoadCRGrid();
                        break;
                    }
                    case "adverseEvents":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.ProtocolProcessId) + 1].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[(int) BoardReviewIdIndex.AdverseEvents].Controls[0]).Text;
                        boardStatus = e.Item.Cells[((int) ReviewCellIndexes.Status) + 1].Text;
                        notificationLetterId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.IRBNotes) + 1].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(int) FileUploadIndex.AdverseEvents].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        adverseEvents.EditItemIndex = -1;
                        pageCache[AdverseEventReviewsKey] = null;
                        LoadAEGrid();
                        break;
                    }

                    case "otherEvents":
                    {
                        annunciator.Message = string.Empty;
                        protocolProcessId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.ProtocolProcessId) + 2].Controls[1]).Text;
                        boardReviewId = ((TextBox) e.Item.Cells[((int) ReviewCellIndexes.BoardReviewId) + 2].Controls[0]).Text;
                        boardStatus = e.Item.Cells[((int) ReviewCellIndexes.Status) + 2].Text;
                        notificationLetterId = ((Label) e.Item.Cells[((int) ReviewCellIndexes.IRBNotes) + 2].Controls[1]).Text;
                        if (removeDocument &&
                            (notificationLetterId != string.Empty) && Convert.ToInt32(notificationLetterId) > 0)
                        {
                            ProtocolManager.DeleteNotificationLetter(
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId)
                                , DataAccess.ConnectionString
                                , Protocol.ProtocolNumber);
                        }
                        else
                        {
                            ScanAndSaveNotificationLetters(((FileUpload) e.Item.Cells[(int) FileUploadIndex.OtherEvents].Controls[1]).PostedFile,
                                (protocolProcessId == string.Empty) ? 0 : Convert.ToInt32(protocolProcessId),
                                (boardReviewId == string.Empty) ? 0 : Convert.ToInt32(boardReviewId),
                                boardStatus,
                                Protocol.ProtocolNumber,
                                (notificationLetterId == string.Empty) ? 0 : Convert.ToInt32(notificationLetterId));
                        }
                        otherEvents.EditItemIndex = -1;
                        pageCache[OtherEventReviewsKey] = null;
                        LoadOEGrid();
                        break;
                    }
                }

                boundFirstIR = false;
                currentFormsId = string.Empty;
                LoadIRGrid();
                BindGrids();
                //Reset the hiddenfield value used to identify whether or not the docuemnt should be removed
                ResetHiddenField();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #endregion

        #region Web Form Designer generated code

        ///<summary>Initializes components used by the page.</summary>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.humansSubModNavigation.Navigate += new PHSRAG.Insight21.InsightWebControls.HumansSubModuleNavigation.NavigateEventHandler(this.OnHumansSubModNavigate);
            this.animalsSubModNavigation.Navigate += new CommandEventHandler(this.OnNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnBreadCrumbNavigate);
            // this.viewFullApplication.Click += new ImageClickEventHandler(OnViewFullApplication);
            this.initialReviewToggler.Click += new System.Web.UI.ImageClickEventHandler(this.OnIRClick);
            this.initialReview.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnIRItemCommand);
            this.initialReview.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnIRItemDataBound);
            this.crToggle.Click += new System.Web.UI.ImageClickEventHandler(this.OnCRClick);
            this.continuingReviews.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.continuingReviews.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.trToggle.Click += new System.Web.UI.ImageClickEventHandler(this.OnTRClick);
            this.triennialReviews.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.triennialReviews.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.amToggler.Click += new System.Web.UI.ImageClickEventHandler(this.OnAMClick);
            this.amendments.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.amendments.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.aeToggler.Click += new System.Web.UI.ImageClickEventHandler(this.OnAEClick);
            this.adverseEvents.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.adverseEvents.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.oeToggler.Click += new System.Web.UI.ImageClickEventHandler(this.OnOEClick);
            this.otherEvents.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.otherEvents.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            cloneProtocol.Click += new ImageClickEventHandler(OnCloneProtocol);
            this.Load += new System.EventHandler(this.OnPageLoad);

            this.initialReview.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);
            this.amendments.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);
            this.continuingReviews.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);
            this.triennialReviews.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);
            this.adverseEvents.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);
            this.otherEvents.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridEdit);

            this.initialReview.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);
            this.amendments.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);
            this.continuingReviews.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);
            this.triennialReviews.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);
            this.adverseEvents.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);
            this.otherEvents.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridUpdate);

            this.initialReview.PreRender += new EventHandler(OnGridPreRender);
            this.amendments.PreRender += new EventHandler(OnGridPreRender);
            this.continuingReviews.PreRender += new EventHandler(OnGridPreRender);
            this.triennialReviews.PreRender += new EventHandler(OnGridPreRender);
            this.adverseEvents.PreRender += new EventHandler(OnGridPreRender);
            this.otherEvents.PreRender += new EventHandler(OnGridPreRender);

            this.initialReview.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
            this.amendments.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
            this.continuingReviews.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
            this.triennialReviews.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
            this.adverseEvents.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
            this.otherEvents.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnGridCancel);
        }

        #endregion

        #region StatefulToggleButton class

        /// <summary>
        /// Provides storing of state for an image button
        /// </summary>
        private class StatefulToggleButton : ImageButton
        {
            #region Constants

            /// <summary>
            /// key used to store button's state (expanded or collapsed) in session
            /// </summary>
            private const string ButtonStateKey = "buttonState";

            #endregion

            /// <summary>
            /// used to store the button's state
            /// </summary>
            private Hashtable cache;

            #region Constructor

            /// <summary>
            /// Creates an image button with a + image if its not been created, otherwise
            /// retrieves the state from session and sets the image based on whether its
            /// in expanded/collapsed mode
            /// </summary>
            /// <param name="gridName">used with index to create id of button</param>
            /// <param name="index">used with gridName to create id of button</param>
            /// <param name="cache">the page's hashtable for storage</param>
            public StatefulToggleButton(string gridName, int index, Hashtable cache)
            {
                this.cache = cache;
                ID = string.Format("isExpanded_{0}_{1}", gridName, index);
                ImageUrl = IsExpanded ? CollapseImageURL : ExpandImageURL;
                CommandName = "ToggleRows";
            }

            #endregion

            #region Properties

            /// <summary>
            /// Whether the button is in an expanded state
            /// </summary>
            public bool IsExpanded
            {
                get
                {
                    string state = cache[ID] as string;
                    return (state == null) ? (IsExpanded = false) : Convert.ToBoolean(state);
                }
                set { cache[ID] = value.ToString(); }
            }

            #endregion

            #region Public Methods

            /// <summary>
            /// Toggle the state of the button (its appearance and the bool that stores
            /// its state)
            /// </summary>
            public void ToggleExpandedState()
            {
                IsExpanded = !IsExpanded;
                ImageUrl = IsExpanded ? CollapseImageURL : ExpandImageURL;
            }

            #endregion
        }

        #endregion

        #region Amendment Cell Indexes

        private enum AmendmentCellIndexes
        {
            ParentRowIndicator,
            Blank,
            FormsId,
            SponsorAmendmentNumber,
            ReceivedDate,
            BoardName,
            ReviewType,
            Status,
            StatusModifiedDate,
            ResponseDate,
            ReviewNotes,
            WorkflowHistory,
            ProtocolProcessId,
            BoardReviewId,
            View,
            FileUpload,
            Remove,
            Edit
        }

        #endregion

        #region ContinuingReview Cell Indexes

        private enum ContinuingReviewCellIndexes
        {
            ParentRowIndicator,
            Blank,
            FormsId,
            ReceivedDate,
            CRStatus,
            BoardName,
            ReviewType,
            MeetingDate,
            Status,
            StatusModifiedDate,
            ResponseDate,
            ReviewNotes,
            WorkflowHistory,
            ProtocolProcessId,
            BoardReviewId,
            View,
            FileUpload,
            Remove,
            Edit
        }

        #endregion

        #region Review Cell Indexes

        private enum ReviewCellIndexes
        {
            PlusSignIndex,
            ReceivedDate,
            BoardName,
            ReviewType,
            MeetingDate,
            Status,
            StatusModifiedDate,
            ResponseDate,
            IRBNotes,
            WorkflowHistory,
            ProtocolProcessId,
            BoardReviewId,
            View,
            FileUpload,
            Remove,
            Edit
        }

        #endregion

        #region NoteIndex Enumeration

        private enum NoteIndex
        {
            InitialReview = 8,
            ContinuingReviews = 11,
            Amendments = 10,
            AdverseEvents = 9,
            OtherEvents = 10,
            TriennialReview = 11
        }

        #endregion

        #region ViewApplicationIndex Enumeration

        private enum ViewApplicationIndex
        {
            InitialReview = 12,
            ContinuingReviews = 15,
            Amendments = 14,
            AdverseEvents = 13,
            OtherEvents = 14,
            TriennialReviews = 15
        }

        #endregion

        #region WorkFlowReportIndex Enumeration

        private enum WorkFlowReportIndex
        {
            InitialReview = 9,
            ContinuingReviews = 12,
            Amendments = 11,
            AdverseEvents = 10,
            OtherEvents = 11,
            TriennialReviews = 12
        }

        #endregion

        #region BoardReviewIdIndex Enumeration

        private enum BoardReviewIdIndex
        {
            InitialReview = 11,
            ContinuingReviews = 14,
            Amendments = 13,
            AdverseEvents = 12,
            OtherEvents = 13,
            triennialEvents = 14
        }

        #endregion

        #region FileUploadIndex Enumeration

        private enum FileUploadIndex
        {
            InitialReview = 13,
            ContinuingReviews = 16,
            Amendments = 15,
            AdverseEvents = 14,
            OtherEvents = 15,
            triennialEvents = 16
        }

        #endregion

        #region Edit Enumeration

        private enum Edit
        {
            InitialReview = 15,
            ContinuingReviews = 18,
            Amendments = 17,
            AdverseEvents = 16,
            OtherEvents = 17,
            triennialEvents = 18
        }

        #endregion

        #region Remove Enumeration
        private enum Remove
        {
            InitialReview = 14,
            ContinuingReviews = 17,
            Amendments = 16,
            AdverseEvents = 15,
            OtherEvents = 16,
            triennialEvents = 17
        }
        #endregion

        #region Common Cell Index Enumerations
        /// <summary>
        /// These indexes are common for all grids EXCEPT Initial Reviews grid
        /// </summary>
        private enum CommonCellIndexes
        {
            ParentRowIndicatorIndex,
            PlusSignIndex,
            FormsIdIndex
        }

        #endregion     
    }
}